package com.seamtop.cuber.common.params;

import com.seamtop.cuber.common.base.DataObject;
import com.seamtop.cuber.common.entriy.*;
import com.seamtop.cuber.common.exception.CuberParamsProcessException;
import com.seamtop.cuber.common.metadata.Column;
import com.seamtop.cuber.common.metadata.RowKey;
import com.seamtop.cuber.common.metadata.TableMetaData;
import com.seamtop.cuber.common.util.StringUtil;

import java.util.HashMap;
import java.util.List;

/**
 * Created by feng on 2015/8/8.
 * 参数校验实体类
 */
public class ParamsCalibration {

    //参数验证
    public static void calibration(CuberMessage message,HashMap<String,TableOperatorBean> operatorBeanMap,HashMap<String,TableMetaData> metaDataMap) throws Exception{
        HashMap<String,Object> dataMap = message.getMsgData();
        if(dataMap == null || dataMap.size() == 0){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_IS_NULL,null).toString());
        }

        String msgType = message.getMsgType();
        TableOperatorBean operatorBean = operatorBeanMap.get(msgType);
        if(operatorBean == null){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_FORMAT_ERROR,null).toString());
        }

        TableMetaData tableMetaData = metaDataMap.get(operatorBean.getOperatorTable());
        if(tableMetaData == null){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.TABLE_ISNOT_EXIST,operatorBean.getOperatorTable()).toString());
        }

        switch (operatorBean.getOperatorType()){
            case TableOperatorType.TABLE_OPERATOR_TYPE_ADD:
                caliAddOperatorParams(dataMap, tableMetaData);
                break;
            case TableOperatorType.TABLE_OPERATOR_TYPE_DELETE:
                caliDeleteOperatorParams(dataMap,tableMetaData);
                break;
            case TableOperatorType.TABLE_OPERATOR_TYPE_UPDATE:
                caliUpdateOperatorParams(dataMap,tableMetaData);
                break;
            case TableOperatorType.TABLE_OPERATOR_TYPE_INCREMENT:
                caliIncrementOperatorParams(dataMap,tableMetaData);
                break;
        }
    }

    public static boolean caliDeleteOperatorParams(HashMap<String,Object> dataMap,TableMetaData tableMetaData) throws Exception{
        RowKey rowKey = tableMetaData.getRowKey();
        if(StringUtil.isEmpty(dataMap.get(rowKey.getKeyName()))|| dataMap.size() != 1){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_ISNOT_EXIST, rowKey.getKeyName()).toString());
        }
        return true;
    }

    public static <T extends Object> boolean caliUpdateOperatorParams(HashMap<String,T> dataMap,TableMetaData tableMetaData) throws Exception{

        RowKey rowKey = tableMetaData.getRowKey();
        if(StringUtil.isEmpty(dataMap.get(rowKey.getKeyName()))){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_ISNOT_EXIST, rowKey.getKeyName()).toString());
        }

        HashMap<String,Column> columnMap = tableMetaData.getColumnMap();
        for(String param : dataMap.keySet()){
            String value = dataMap.get(param)+"";
            int valueType = 0;
            int maxSize = 0;
            if(rowKey.getKeyName().equals(param)){
                valueType = rowKey.getKeyType();
                maxSize = rowKey.getKeyMaxSize();
            }else{
                Column column = columnMap.get(param);
                if(column == null){
                    throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_ISNOT_EXIST, param).toString());
                }
                valueType = column.getColumnType();
                maxSize = column.getColumnMaxSize();
            }
            //数据类型判断
            if(valueType != 0){
                boolean result = isTypeCorrect(valueType,value);
                if(!result){
                    throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_FORMAT_ERROR, param).toString());
                }
            }
            //数据长度判断
            if(maxSize > 0 && value.length() > maxSize){
                throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_FORMAT_ERROR, param).toString());
            }

        }
        return true;
    }


    public static <T extends Object> boolean caliIncrementOperatorParams(HashMap<String,T> dataMap,TableMetaData tableMetaData) throws Exception{
        HashMap<String,Column> columnMap = tableMetaData.getColumnMap();
        for(String param : dataMap.keySet()){
            if(param.startsWith(CuberContants.CUBER_PARAMS_KEYPREFIX)){
                continue;
            }
            RowKey rowKey = tableMetaData.getRowKey();
            String value = dataMap.get(param)+"";
            int valueType = 0;
            boolean isRequired = false;
            int maxSize = 0;
            Column column = columnMap.get(param);
            if(column == null){
                throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_ISNOT_EXIST, param).toString());
            }
            isRequired = column.isIfRequired();
            valueType = column.getColumnType();
            maxSize = column.getColumnMaxSize();

            //数据类型判断
            if(valueType != 0){
                boolean result = isTypeCorrect(valueType,value);
                if(!result){
                    throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_FORMAT_ERROR, param).toString());
                }
            }
            //是否必填
            if(isRequired && StringUtil.isEmpty(value)){
                throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_IS_NULL, param).toString());
            }
            //数据长度判断
            if(maxSize > 0 && value.length() > maxSize){
                throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_FORMAT_ERROR, param).toString());
            }
        }
        for(String param : columnMap.keySet()){
            Column column = columnMap.get(param);
            if(column.isIfRequired() && StringUtil.isEmpty(dataMap.get(param)) && !column.isJoinColumn()){
                throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_IS_NULL, param).toString());
            }
        }
        return true;
    }



    public static <T extends Object> boolean caliAddOperatorParams(HashMap<String,T> dataMap,TableMetaData tableMetaData) throws Exception{

        HashMap<String,Column> columnMap = tableMetaData.getColumnMap();
        for(String param : dataMap.keySet()){
            RowKey rowKey = tableMetaData.getRowKey();
            String value = dataMap.get(param)+"";
            int valueType = 0;
            boolean isRequired = false;
            int maxSize = 0;
            if(rowKey.getKeyName().equals(param)){
                isRequired = true;
                valueType = rowKey.getKeyType();
                maxSize = rowKey.getKeyMaxSize();
            }else {
                Column column = columnMap.get(param);
                if(column == null){
                    throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_ISNOT_EXIST, param).toString());
                }
                isRequired = column.isIfRequired();
                valueType = column.getColumnType();
                maxSize = column.getColumnMaxSize();
            }
            if(valueType != 0){
                boolean result = isTypeCorrect(valueType,value);
                if(!result){
                    throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_FORMAT_ERROR, param).toString());
                }
            }
            if(isRequired && StringUtil.isEmpty(value)){
                throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_IS_NULL, param).toString());
            }
            //数据长度判断
            if(maxSize > 0 && value.length() > maxSize){
                throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_FORMAT_ERROR, param).toString());
            }
        }
        //判断XML必填字段传入参数中是否均已包含
        for(String param : columnMap.keySet()){
            Column column = columnMap.get(param);
            if(column.isIfRequired() && StringUtil.isEmpty(dataMap.get(param)+"") && !column.isJoinColumn()){
                throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_IS_NULL, param).toString());
            }
        }
        return true;
    }

    private static boolean isTypeCorrect(int valueType,String str) throws Exception{
        boolean result = false;
        switch (valueType){
            case 1://字符串类型
                result = true;
                break;
            case 2://Int 类型
                result = StringUtil.isNumbric(str);
                break;
            case 3://LONG类型
                result = StringUtil.isNumbric(str);
                break;
            case 4://Float类型
                result = StringUtil.isDouble(str);
                break;
            case 5://Double类型
                result = StringUtil.isDouble(str);
                break;
            case 6://日期类型（日期字符串）
                //result = StringUtil.isNumbric(str);
                break;
            case 7://日期类型（时间戳）
                result = StringUtil.isNumbric(str);
                break;
            default:
                result = false;
                break;
        }
        return result;
    }


    public static HttpReturn validate(String validatorId,HashMap<String,String> paramsMap){
        Validator validator = DataObject.getCuberValidatorMap().get(validatorId);
        if(validator == null){
            return new HttpReturn(HttpReturn.RETURN_CODE_FAILURE,"validatorId is not exist!");
        }
        List<ValidatorItem> itemList = validator.getItemList();
        if(itemList == null || itemList.size() == 0){
            return new HttpReturn(HttpReturn.RETURN_CODE_SUCCESS,"success!");
        }

        for (int i=0;i<itemList.size();i++){
            ValidatorItem item = itemList.get(i);
            String param = item.getParamName();
            String paramValue = paramsMap.get(param);
            String validateMethod = item.getValidateMethod();
            boolean isRequired = item.isRequired();
            if(isRequired && StringUtil.isEmpty(paramValue)){
                return new HttpReturn(HttpReturn.RETURN_CODE_FAILURE,"param "+ param +" is null!");
            }else if (!isRequired && StringUtil.isEmpty(paramValue)){
                continue;
            }else{
                boolean res = validate(paramValue,validateMethod);
                if(!res){
                    return new HttpReturn(HttpReturn.RETURN_CODE_FAILURE,"param " + param + " format error");
                }
            }
        }
        return new HttpReturn(HttpReturn.RETURN_CODE_SUCCESS,"success!");
    }


    public static boolean validate(String paramValue,String validateMethod){
        if(StringUtil.isEmpty(validateMethod) || StringUtil.isEmpty(paramValue)){
            return false;
        }
        if(ValidateConstants.VALIDATE_METHOD_ISNOTNULL.equals(validateMethod)){
            return !StringUtil.isEmpty(paramValue);
        }else if(ValidateConstants.VALIDATE_METHOD_ISNUM.equals(validateMethod)){
            return StringUtil.isNumbric(paramValue);
        }else if(ValidateConstants.VALIDATE_METHOD_ISDOUBLE.equals(validateMethod)){
            return StringUtil.isDouble(paramValue);
        }
        return true;
    }


}
